home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / st_asy.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  13KB  |  485 lines

  1. /*
  2.     serial device interface for Atari ST
  3.  
  4.     v0.00 01.01.93 DFN Initial Version
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <dos.h>        
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <osbind.h>
  13.  
  14. #include "global.h"
  15. #include "config.h"
  16. #include "mbuf.h"
  17. #include "internet.h"
  18. #include "iface.h"
  19. #include "st.h"
  20. #include "cmdparse.h"
  21. #include "asy.h"
  22. #include "st_asy.h"
  23. #include "devparam.h"
  24.  
  25. struct asy Asy[ASY_MAX];
  26. void __asy_rxover(void);
  27. void __asy_txover(void);
  28. void __stdargs asy_tx(int dev, void *p1, void *p2);
  29. void asy_flush(int dev);
  30.  
  31. void        (*rxover)();
  32. void        (*txover)();
  33. void     int_rxover(void);
  34. void        int_txover(void);
  35.  
  36. /* Interface list header */
  37.  
  38. int Nasy = 0;                                        /* number of async devices             */
  39.  
  40. int TX_pwait = 0;
  41.  
  42. /*
  43.     asy_init - Initialize async port "dev"
  44. */
  45.  
  46. int asy_init(int dev,
  47.                 struct iface *iface,
  48.                 char    *addr,
  49.                 char    *vec,
  50.                 int16 bufsize,
  51.                 int    trigchar,
  52.                 char    monitor,
  53.                 long    speed)
  54. {
  55.     char   *ifn;
  56.     char   *bufp_in, *bufp_out;
  57.     struct iorec *ip;
  58.     struct asy *asy;
  59.  
  60.     Nasy++;
  61.     asy = &Asy[dev];
  62.  
  63.     asy->iface             = iface;                    /* link up to interface structure */
  64.     asy->rxchar         = 0;
  65.     asy->txchar         = 0;
  66.     asy->rxover       = 0;
  67.     asy->txover            = 0;
  68.     asy->mode             = trigchar;
  69.     asy->input_active = 0;
  70.     asy->device_name     = strdup(addr);
  71.     asy->unit             = atoi(vec);
  72.     asy->buflen         = bufsize;
  73.     asy->vec             = atoi(vec);            /* dev to resend bytes to */
  74.     asy->addr             = 1;
  75.  
  76.     /*
  77.         force user to allocate more memory than he already has.
  78.        If no memory is allocated, asy_stop() may behave funny...
  79.     */
  80.     
  81.     if (bufsize <= 256)    /* only allocate a bigger buffer */
  82.         return -1;
  83.  
  84.     if ((bufp_in = malloc(bufsize)) == NULLCHAR){
  85.         printf("asy_init(%d): no memory for rx buffer \n", dev);
  86.         return -1;
  87.     }
  88.  
  89.     if ((bufp_out = malloc(bufsize)) == NULLCHAR){
  90.         printf("asy_init(%d): no memory for tx buffer \n", dev);
  91.         return -1;
  92.     }
  93.  
  94.     /* Save original IOREC values */
  95.  
  96.     ip = Iorec((asy->addr)-1);    /* Iorec wants AUX: = 0, MIDI = 2 */
  97.  
  98.     Jdisint(12);                    /* disable RS-232 interrupt */
  99.  
  100.     asy->in = ip;
  101.     memcpy(&asy->oldin, ip, sizeof(struct iorec));
  102.     
  103.     if (asy->addr == RS232) {    /* increase RS-232 transmit buffer?         */
  104.         ip++;
  105.         asy->out = ip;
  106.         memcpy(&asy->oldout,ip,sizeof(struct iorec));
  107.     }
  108.  
  109. /* Set up receiver FIFO                                                                     */
  110.     
  111.     asy->in->ibuf         = bufp_in;                        /* buffer pointer                */
  112.     asy->in->ibufsiz     = bufsize;                        /* size                            */
  113.     asy->in->ibufhd     = asy->in->ibuftl = 0;        /* head & tail indices        */
  114.     asy->in->ibuflow    = bufsize / 4;                    /* low water mark                */
  115.     asy->in->ibufhi     = bufsize - (bufsize / 4);    /* high water mark            */
  116. #if 0
  117.     asy->out->ibuf     = bufp_out;                        /* buffer pointer                */
  118.     asy->out->ibufsiz = bufsize;                        /* size                            */
  119.     asy->out->ibufhd     = asy->out->ibuftl = 0;    /* head & tail indices        */
  120.     asy->out->ibuflow = bufsize / 4;             /* low water mark          */
  121.     asy->out->ibufhi     = bufsize - (bufsize / 4);    /* high water mark            */
  122. #endif
  123.     txover = Setexc(73, int_txover);            /* link in overrun handlers        */
  124.     rxover = Setexc(75, int_rxover);
  125.  
  126.     Jenabint(12);                                    /* enable RS-232 interrupts         */
  127.     Offgibit(0xEF);                                /* raise DTR                            */
  128.     
  129.     asy->input_len         = 0;                    /* clear input buffer                 */
  130.     asy->input_active     = 0;
  131.     asy->serial_open         = 1;
  132.     asy->output_active     = 0;
  133.  
  134.     asy_speed(dev, speed);
  135.     
  136.     iface->txproc = newproc( ifn = if_name(iface," tx"),  /* tx thread      */
  137.             256, asy_tx, dev, iface, NULL, 0);
  138.  
  139.     return (int)Nasy;
  140. }
  141.  
  142. /*****************************************************************************
  143.     asy_stop  - restore old iorec and frees memory allocated to the RS-232
  144.                     buffers.  Cycle DTR to force modem to drop the line. 
  145. *****************************************************************************/
  146.  
  147. int asy_stop(struct iface *iface)
  148. {
  149.     struct asy *asy;
  150.     
  151.     asy = &Asy[iface->dev];
  152.  
  153. #ifdef DEBUG
  154.     printf("asy_stop: iface=0x%lx dev=%d \n", iface, iface->dev);
  155.     fflush(stdout);
  156. #endif
  157.  
  158.     (void)Jdisint(12);        /* disable RS-232 interrupts */
  159.  
  160.     Setexc(73, txover);                            /* restore overrun handlers        */
  161.     Setexc(75, rxover);        
  162.  
  163.     free(asy->in->ibuf);        /* free the buffer */
  164.  
  165.     /* Restore old iorecs */
  166.     
  167.     memcpy(asy->in, &asy->oldin, sizeof(struct iorec));
  168.     
  169.     if (asy->addr == RS232)    {
  170.         int32    t;                                        /* temporary timer variable        */
  171.  
  172.         memcpy(asy->out, &asy->oldout, sizeof(struct iorec));
  173.   
  174.         Ongibit(0x10);                                    /* drop DTR, so modem drops line */    
  175.         t = 500 + msclock();                   /* get time + 500ms              */
  176.         while (t > msclock())                        /* wait                          */
  177.             ;
  178.         Offgibit(0xEF);                        /* raise DTR                     */
  179.     }
  180.     
  181.     (void)Jenabint(12);                                /* enable RS-232 interrupts */ 
  182.  
  183.     Nasy--;
  184.     return 0;
  185. }
  186.  
  187. /*****************************************************************************
  188.     asy_speed - Set async line speed
  189. *****************************************************************************/
  190. int asy_speed(int dev, long speed)
  191. {
  192.     int baud;                                         /* int result; */
  193.     struct    asy *asy;
  194.  
  195.     asy = &Asy[dev];
  196.     
  197.     if (speed <= 0 || dev >= Nasy)
  198.         return -1;
  199.  
  200.     asy->speed = speed;            /* shouldn't this be done in slip.c? */
  201.  
  202.     switch (speed) {
  203.         case 300:
  204.             baud = 9;    /* how slow can you get? :-) */
  205.             break;
  206.         case 1200:
  207.             baud = 7;
  208.             break;
  209.         case 2400:
  210.             baud = 4;
  211.             break;
  212.         case 4800:
  213.             baud = 2;
  214.             break;
  215.         case 9600:
  216.             baud = 1;
  217.             break;
  218.         case 19200:
  219.             baud = 0;
  220.             break;
  221.         case 38400:
  222.             Rsconf(0,2,0x08,-1,-1,-1);
  223.             Xbtimer(3,1,8,(void *)-1);
  224.             asy_flush(dev);
  225.             return 0;
  226.         default:
  227.             printf("asy_speed: unknown RS-232 speed (%d).\n", speed);
  228.             return -1;
  229.     }
  230. /*    (void) Rsconf(baud,0,0x88,-1,-1,-1); */    /* no flow control     */
  231.     (void) Rsconf(baud,2,0x88,-1,-1,-1);        /* RTS/CTS enabled    */
  232.     asy_flush(dev);
  233.  
  234.     return 0;
  235. }
  236.  
  237. /*****************************************************************************
  238.     asy_flush - flush the input buffer of device dev (either aux: or midi)
  239.    May be useful, because setting the baudrate causes an 0x7f to be sent.
  240. *****************************************************************************/
  241.  
  242. void asy_flush(int dev)
  243. {
  244.     int st_dev;
  245.     long c;                    /* Bconin returns a long */
  246.     struct asy *asy = &Asy[dev];
  247.  
  248.     st_dev = asy->addr;
  249.  
  250.     while (Bconstat(st_dev) == -1) {            /* at least 1 char available        */
  251.         c = Bconin(st_dev);                        /* read character                        */
  252.     }
  253. }
  254.  
  255. /*****************************************************************************
  256.     asy_ioctl - Async line control
  257. *****************************************************************************/
  258.  
  259. int32 asy_ioctl (struct iface *iface, int cmd, int set, int32 val)
  260. {
  261.     int32    retval;
  262.     struct asy *asy;
  263.     
  264.     asy = &Asy[iface->dev];
  265.  
  266.     switch (cmd) {
  267.         case PARAM_SPEED:
  268.             if (set)
  269.                 asy_speed(iface->dev, val);
  270.             return Asy[iface->dev].speed;
  271.  
  272.         case PARAM_DTR:
  273.             if (set) {
  274.                 val ?  Offgibit(0xEF) : Ongibit(0x10);
  275.                 asy->dtr_usage = (val) ? MOVED_UP : MOVED_DOWN;
  276.             }
  277.             retval = Giaccess(0, 0x0E) & 0x10;         /* get DTR status                */
  278.             tprintf("DTR is %s \n", retval ? "DOWN" : "UP");
  279.             return retval ? 0 : 1;
  280.  
  281.         case PARAM_RTS:
  282.             if (set) {
  283.                 val ? Offgibit(0xF7) : Ongibit(0x08);
  284.                 asy->rts_usage = (val) ? MOVED_UP : MOVED_DOWN;
  285.             }
  286.             retval = Giaccess(0, 0x0E) & 0x08;        /* get RTS status                */
  287.             tprintf("RTS is %s \n", retval ? "DOWN" : "UP");
  288.             return retval ? 0 : 1;
  289.                         
  290.         case PARAM_UP:
  291.             Offgibit(0xF7);                        /* raise RTS                            */
  292.             Offgibit(0xEF);                        /* raise DTR                            */
  293.             asy->rts_usage = MOVED_UP;
  294.             asy->dtr_usage = MOVED_UP;
  295.             return TRUE;
  296.  
  297.         case PARAM_DOWN:
  298.             Ongibit(0x08);                            /* drop RTS                                */
  299.             Ongibit(0x10);                            /* drop DTR                                */
  300.             asy->rts_usage = MOVED_DOWN;
  301.             asy->dtr_usage = MOVED_DOWN;
  302.             return FALSE;
  303.         }
  304.  
  305.  
  306.     return FALSE;
  307. }
  308.  
  309. /***********************************************************************
  310.     asy_rxover - RS232 receiver overrun interrupt handler
  311. ***********************************************************************/
  312.  
  313. void __saveds asy_rxover(void)
  314. {
  315.     struct asy *asy = &Asy[0];
  316.  
  317.     asy->rxover = asy->rxover + 1;
  318. }
  319. /***********************************************************************
  320.     asy_txover - RS232 transmitter overrun interrupt handler
  321. ***********************************************************************/
  322.  
  323. void __saveds asy_txover(void)
  324. {
  325.     struct asy *asy = &Asy[0];
  326.  
  327.     asy->txover = asy->txover + 1;
  328. }
  329.  
  330.  
  331.  
  332. /*****************************************************************************
  333.     get_asy - Receive character from asynch line, called from slip.c
  334.                  Blocks if no character available.  Returns -1 if pwait is
  335.                  interrupted.
  336. *****************************************************************************/
  337.  
  338. int get_asy(int dev)
  339. {
  340.      struct asy *asy = &Asy[dev];
  341.     
  342.     while (Bconstat(asy->addr) == 0)            /* 0 - no char, -1 char available    */
  343.         if (pwait(NULL) != 0)                    /* giveup the CPU if no char             */
  344.             return -1;                                /* signal received                        */
  345.             
  346.     asy->input_len--;
  347.     asy->rxchar++;                                    /* total number of chars received     */
  348.  
  349.     return Bconin(asy->addr);                    /* return i/p character                    */
  350.  
  351. }
  352.  
  353. /*****************************************************************************
  354.     asy_len - get length of async input queue
  355.               returns 1 if characters are available, else 0
  356. *****************************************************************************/
  357.  
  358. int asy_len(int dev)
  359. {
  360.      struct asy *asy = &Asy[dev];
  361.     
  362.     if (Bconstat(asy->addr) == 0)            /* 0 - no char, -1 char available    */
  363.         return 0;                                /* no characters waiting                */
  364.     else
  365.         return 1;                                /* 1 or more characters waiting        */    
  366. }
  367.  
  368. /*****************************************************************************
  369.     asy_send - queue an mbuf to the async device, called from slip.c
  370. *****************************************************************************/
  371.  
  372. int asy_send(int dev, struct mbuf *bp)
  373. {
  374.     if (dev < 0 || dev >= Nasy)
  375.         return -1;
  376.  
  377.     enqueue(&Asy[dev].sndq, bp);
  378.  
  379.     return 0;
  380. }
  381.  
  382. /*****************************************************************************
  383.     asy_tx - send mbufs to the serial device
  384. *****************************************************************************/
  385.  
  386. void __stdargs asy_tx(int dev, void *p1, void *p2)
  387. {
  388.     int st_dev;
  389.     unsigned short i = 0;
  390.     struct mbuf *bp;
  391.     struct asy *asy = &Asy[dev];
  392.  
  393.     st_dev = asy->addr;
  394.     
  395.     for( ; ;) {
  396.         while (asy->sndq == NULLBUF)
  397.             pwait(&asy->sndq);
  398.  
  399.         bp = dequeue(&asy->sndq);
  400.  
  401.         if (bp != NULLBUF) {
  402.             for (i = 0; i < bp->cnt; ++i) {
  403.                 while (Bcostat(st_dev) == 0) {        /* if serial device not ready         */
  404.                     TX_pwait += 1;                            /* inc the wait count             */
  405.                     pwait(NULL);                            /*    giveup the CPU                     */
  406.                 }
  407.                 (void)Bconout(st_dev, bp->data[i]);    /* xmit byte 1= AUX: 3=MIDI:         */
  408.            }
  409.             asy->txchar += bp->cnt;                        /* increase count of tx chars     */
  410.         }
  411.         bp = free_mbuf(bp);                                /* do next buf on chain         */
  412.     }
  413. }
  414.  
  415. int stxrdy(int dev)
  416. {
  417.     return Asy[dev].output_active == 0;
  418. }
  419.  
  420. static void asyinfo(struct asy *asy, int verbose)
  421. {
  422.     short    tx_head, tx_tail;                            
  423.     short rx_head, rx_tail;
  424.     short chars_in, chars_out;
  425.  
  426.     tx_head = asy->out->ibufhd;                    /* transmitter head pointer    */
  427.     tx_tail = asy->out->ibuftl;                    /* transmiter tail pointer        */
  428.  
  429.     rx_head = asy->in->ibufhd;                        /* receiver head pointer        */
  430.     rx_tail = asy->in->ibuftl;                        /* receiver tail pointer        */
  431.     
  432.     if ((chars_in  = rx_head - rx_tail) < 0)
  433.         chars_in = asy->in->ibufsiz - rx_tail + rx_head;
  434.  
  435.     if ((chars_out = tx_head - tx_tail) < 0)
  436.         chars_out = asy->out->ibufsiz - tx_tail + tx_head;
  437.  
  438.     tprintf("%s: %8d baud (%s unit %d)\n",
  439.         asy->iface->name, asy->speed, asy->device_name, asy->unit);
  440.         
  441.     tprintf(" RX: %8lu chars %8lu o/r %6d in buf (H=%d T=%d B=%d)\n",
  442.                 asy->rxchar, asy->rxover, chars_in,
  443.                 asy->in->ibufhd, asy->in->ibuftl, asy->in->ibufsiz);
  444.                 
  445.     tprintf(" TX: %8lu chars %8lu o/r %6d in buf (H=%d T=%d B=%d)\n",
  446.                 asy->txchar, asy->txover, chars_out,
  447.                 asy->out->ibufhd, asy->out->ibuftl, asy->out->ibufsiz); 
  448.     tprintf("     pwait = %d \n", TX_pwait);
  449. }
  450.  
  451. /*****************************************************************************
  452.     doasystat - 
  453. *****************************************************************************/
  454.  
  455. int doasystat(int argc, char *argv[], void *envp)
  456. {
  457.     struct asy *asy;
  458.     int i;
  459.  
  460.     if (!Nasy) {
  461.         tprintf("No asy interfaces attached.\n");
  462.         return -1;
  463.     }
  464.  
  465.     if (argc> 1) {
  466.         for (i = 1; i < argc; i++) {
  467.             struct asy *dev = NULL;
  468.  
  469.             for (asy = &Asy[0]; asy < &Asy[Nasy]; asy++) {
  470.                 if (strcmp(asy->iface->name, argv[i]) == 0) {
  471.                     dev = asy;
  472.                     break;
  473.                 }
  474.             }
  475.             if (dev)
  476.                 asyinfo(dev, 1);
  477.             else
  478.                 tprintf("Unknown device '%s'\n", argv[i]);
  479.         }
  480.     } else 
  481.         /* just dump them all out */
  482.         for (asy = &Asy[0]; asy < &Asy[Nasy]; asy++)
  483.             asyinfo(asy, 0);
  484. }
  485.